home *** CD-ROM | disk | FTP | other *** search
/ Programmers Heaven 2 / Programmers Heaven 2.iso / files / graphics / library / wgt51_r2.zip / WGT5 / EXAMPLES / WGT54.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-03  |  11.8 KB  |  451 lines

  1. /*
  2. ==============================================================================
  3.               WordUp Graphics Toolkit Version 5.0                     
  4.                  Demonstration Program 54                         
  5.                                           
  6.  This program demonstrates how to use the 3D library along with the polygon  
  7.  routines.  It rotates a pyramid object using Gouraud shading.               
  8.                                           
  9.  *** PROJECT ***                                                             
  10.  This program requires the file WGT5_WC.LIB, and WGT3D_WC.LIB to be linked.  
  11.                                           
  12.  *** DATA FILES ***                                                          
  13.  You must have the MYTRI.3D and 3DDEMO.PAL files in your executable dir.     
  14.                                           
  15. ==============================================================================
  16. */
  17.  
  18. #include <conio.h>
  19. #include <time.h>
  20. #include <ctype.h>
  21. #include <wgt5.h>
  22. #include <wgt3d.h>
  23.  
  24. /*
  25. This is an interactive program and requires user to use keys to rotate 
  26. the object:
  27.  Keys used (on keypad):
  28.      7 8 : decrease/increase x rotation
  29.      4 5 : decrease/increase y rotation
  30.      1 2 : decrease/increase z rotation
  31.      - + : decrease/increase distance
  32.        q : quits program
  33. */
  34.  
  35. #define HOLLOW 0        /* These are the types of polygons we can draw */
  36. #define SOLID 1         
  37. #define GOURAUD 2       /* Lighted shading (not used in this demo) */
  38. #define SETGOURAUD 3    /* Fixed shading (vertices has fixed colors) */
  39.  
  40. #define MAXPOINTS 100   /* Maximum number of points in the object */
  41.  
  42. void loadobject (char *);  /* Load a custom 3D object file format */
  43. void update_screen (void); /* Uses a dirty rectangle approach to copy
  44.                   the smallest area needed to update the
  45.                   screen. */
  46. void calculate_depth (void); /* Finds a depth value for each polygon, used
  47.                 to sort the polygons into a back to front
  48.                 order. */
  49. void sort_polys (void);      /* Sorts the polygons by their depth value */   
  50. void draw_polys (void);      /* Draws the polygons from back to front */
  51. void clear_last (void);      /* Erases the previous frame */
  52. void get_response (void);    /* Reads keys and responds accordingly */
  53.  
  54. point3d mypoints[9];         /* Contains original points of the object */
  55. point3d finp[9];             /* Holds all point after they have bee
  56.                 rotated with wrotatepoints. */
  57.  
  58. tpolypoint mypoly[4];          /* Holds a 4 vertex polygon */
  59.  
  60. short curx = 0;                /* Current rotation values */
  61. short cury = 180;
  62. short curz = 180;
  63.  
  64. int  maxpoly = 300;            /* Holds the number of polygons in the object */   
  65. char c;                        /* user's response from keyboard */
  66.  
  67. int sortpoly[MAXPOINTS];     /* The sorted polygon list */
  68. int ztotal[MAXPOINTS];       /* Depth values for each polygon */
  69. int faces[200][4];           /* Polygon face array.  This holds 4 vertices
  70.                 for each polygon.  All points are rotated
  71.                 and then the polygons are drawn from the
  72.                 resulting points using these vertices.
  73.                 This way polygons that share vertices will
  74.                 not have the same point rotated twice. */
  75. int facetype[200];           /* Holds the type of polygon for each face */
  76.  
  77. block other;                   /* A background screen */
  78. color pal[256];              
  79.  
  80. typedef struct {               /* Dirty rectangle structure */
  81.   short x1;
  82.   short y1;
  83.   short x2;                /* Used to keep track of what portion of the */
  84.   short y2;                /* screen has been changed, so we can update */
  85. } rect;                    /* the least amount of video memory */
  86.  
  87. rect lastrect;             /* Dirty rectangle for the last frame */
  88. rect thisrect;             /* Dirty rectangle for current frame */
  89.  
  90. short xdir = 1;    /* Rotation directions (1, 0, -1) */
  91. short ydir = 1;
  92. short zdir = 1;
  93. short xpos = 0;    /* Object positions */
  94. short ypos = 0;
  95. short zpos = 0;
  96. /* These are arrays to prepare for multiple objects in the next demo */
  97.  
  98.  
  99. /* Loads a custom 3D object file format. */
  100. /* WGT 3D Object File Format
  101. The following is a description of the file format used in the 3D demos.
  102.  
  103. The first line contains the identification string
  104. "WGT 3D Object File"
  105.  
  106. Then the number of points in the file is on a separate line.
  107. Each point is then stated, with the following format:
  108. x_coord y_coord z_coord sx_value sy_value
  109.  
  110. With hollow and solid polygons, you can use sx as the color of the polygon.
  111. With Gouraud shading, sx is the color at that point.
  112. With Texture mapping, sx,sy is the offset into the texture bitmap.
  113.  
  114. A blank line follows, and then the number of faces is on a new line.
  115. Each face is described as a 4 point sequence, using the points stated above.
  116. Point numbers start at 0.
  117. On the same line, a polygon type number is given.
  118. 0 means hollow
  119. 1 means solid
  120. 2 means lighted Gouraud (brighter closer to you)
  121. 3 means set Gouraud (uses value stored by the vertices above)
  122. 4 means texture mapped (not used in this demo)
  123.  
  124. For example, to make a face with points 0-3, with set Gouraud shading,
  125. the line would be
  126. 0 1 2 3 3
  127.  
  128. Here is an example image with one polygon:
  129.  
  130. WGT 3D Object File
  131. 4
  132. -25 -25 50 140 0
  133. 25 -25 50 195 0
  134. 25 25 50 140 0
  135. -25 25 50 195 0
  136.  
  137. 1
  138. 0 1 2 3 3
  139. */
  140. void loadobject (char *fname)
  141. {
  142.   short i;
  143.   short e;
  144.   FILE *objfile;
  145.   char blank[80];
  146.  
  147.   objfile = fopen (fname, "rt");
  148.  
  149.   fscanf (objfile, "%s %s %s %s\n", blank, blank, blank, blank);
  150.  
  151.   /* Number of points in this object */
  152.   fscanf (objfile, "%d\n", &maxpoly);
  153.  
  154.  
  155.   /* Write the points */
  156.   for (i = 0; i < maxpoly; i++)
  157.     fscanf (objfile, "%d %d %d %d %d\n", &mypoints[i].x, &mypoints[i].y, &mypoints[i].z,
  158.         &mypoints[i].sx, &mypoints[i].sy);
  159.  
  160.   /* Number of faces in this object */
  161.   fscanf (objfile, "\n%d\n", &maxpoly);
  162.   for (i = 0; i < maxpoly; i++)
  163.   {
  164.     for (e = 0; e < 4; e++)
  165.        fscanf (objfile, "%d ", &faces[i][e]);
  166.     fscanf (objfile, "%d\n", &facetype[i]);
  167.   }
  168.   fclose (objfile);
  169. }
  170.  
  171.  
  172. void clear_last (void)
  173. {
  174.   /* Do clipping for smallest area update */
  175.   if (lastrect.x1 < 0)
  176.     lastrect.x1 = 0;
  177.   if (lastrect.x2 > 319)
  178.     lastrect.x2 = 319;
  179.   if (lastrect.y1 < 0)
  180.     lastrect.y1 = 0;
  181.   if (lastrect.y2 > 199)
  182.     lastrect.y2 = 199;
  183.   wsetcolor (0);
  184.   wbar (lastrect.x1, lastrect.y1, lastrect.x2, lastrect.y2);
  185.   /* Clear out the area that was drawn in last frame */
  186. }
  187.  
  188.  
  189. void update_screen (void)
  190. {
  191.   if (lastrect.x1 > thisrect.x1)
  192.     lastrect.x1 = thisrect.x1;
  193.   if (lastrect.x2 < thisrect.x2)
  194.     lastrect.x2 = thisrect.x2;
  195.   if (lastrect.y1 > thisrect.y1)
  196.     lastrect.y1 = thisrect.y1;
  197.   if (lastrect.y2 < thisrect.y2)
  198.     lastrect.y2 = thisrect.y2;
  199.   /* See if the previous frame was larger in any direction. If it is, enlarge
  200.      the area so it will copy black over the previous frame. */
  201.  
  202.   /* Do clipping */
  203.   if (lastrect.x1 < 0)
  204.     lastrect.x1 = 0;
  205.   if (lastrect.x2 > 319)
  206.     lastrect.x2 = 319;
  207.   if (lastrect.y1 < 0)
  208.     lastrect.y1 = 0;
  209.   if (lastrect.y2 > 199)
  210.     lastrect.y2 = 199;
  211.  
  212.   wcopyscreen(lastrect.x1, lastrect.y1, lastrect.x2, lastrect.y2, other,
  213.           lastrect.x1, lastrect.y1, NULL);
  214.   /* Copy from our second page to the visual page. */
  215.  
  216.   lastrect.x1 = thisrect.x1;
  217.   lastrect.y1 = thisrect.y1;
  218.   lastrect.x2 = thisrect.x2;
  219.   lastrect.y2 = thisrect.y2;
  220.   /* Make the last rectangle = current rectangle */
  221. }
  222.  
  223.  
  224.  
  225. void calculate_depth (void)
  226. {
  227.   short d;
  228.   short e;
  229.   short points;    /* Total number of unique points */
  230.  
  231.   for (d = 0; d < maxpoly; d++)
  232.   {
  233.     sortpoly[d] = d;
  234.     ztotal[d] = 0;
  235.     ztotal[d] += finp[faces[d][0]].z;
  236.     points = 1;
  237.     for (e = 1; e < 4; e++)
  238.       if (faces[d][e - 1] != faces[d][e]) /* Don't count duplicate points */
  239.       {
  240.     points++;
  241.     ztotal[d] += finp[faces[d][e]].z;
  242.       }
  243.     ztotal[d] /= points;
  244.   }
  245. }
  246.  
  247.  
  248. void sort_polys(void)
  249. {
  250.   short d;
  251.   short e;
  252.   short temp;
  253.  
  254.   for (d = 0; d < maxpoly - 1; d++)
  255.     for (e = d + 1; e < maxpoly; e++)
  256.     {
  257.       if (ztotal[sortpoly[e]] > ztotal[sortpoly[d]])
  258.       {
  259.     temp = sortpoly[e];
  260.     sortpoly[e] = sortpoly[d];
  261.     sortpoly[d] = temp;
  262.       }
  263.     }
  264. }
  265.  
  266.  
  267.  
  268. void draw_polys(void)
  269. {
  270.   short d;
  271.   short e;
  272.   short cp;
  273.  
  274.   for (d = 0; d < maxpoly; d++)
  275.   {
  276.     cp = sortpoly[d];
  277.     for (e = 0; e < 4; e++)
  278.     {
  279.       mypoly[e].x = finp[faces[cp][e]].x;
  280.       mypoly[e].y = finp[faces[cp][e]].y;
  281.       if (facetype[cp] == SETGOURAUD)
  282.     mypoly[e].sx = mypoints[faces[cp][e]].sx;
  283.       else
  284.       {
  285.     mypoly[e].sx = 255 - (finp[faces[cp][e]].z + 80);
  286.     if (mypoly[e].sx < 2)
  287.       mypoly[e].sx = 2;
  288.     if (mypoly[e].sx > 250)
  289.       mypoly[e].sx = 250;
  290.       }
  291.  
  292.       if (mypoly[e].x < thisrect.x1)
  293.     thisrect.x1 = mypoly[e].x;
  294.       if (mypoly[e].x > thisrect.x2)
  295.     thisrect.x2 = mypoly[e].x;
  296.       if (mypoly[e].y < thisrect.y1)
  297.     thisrect.y1 = mypoly[e].y;
  298.       if (mypoly[e].y > thisrect.y2)
  299.     thisrect.y2 = mypoly[e].y;
  300.       /* See if the polygon is larger than the current area to update.
  301.      If it is, enlarge the area so all polygons fit inside. */
  302.     }
  303.     wsetcolor (mypoly[0].sx);
  304.     if (facetype[cp] == HOLLOW)
  305.       whollowpoly (mypoly, 4, 0, 0,CLOSED_POLY);
  306.     else if (facetype[cp] == SOLID)
  307.       wsolidpoly (mypoly, 4, 0, 0,NULL);
  308.     else if ((facetype[cp] == GOURAUD) || (facetype[cp] == SETGOURAUD))
  309.       wgouraudpoly (mypoly, 4, 0, 0);
  310.   }
  311. }
  312.  
  313.  
  314.  
  315. void get_response (void)
  316. {
  317.   if (kbhit ())
  318.     c = toupper (getch ());
  319.  
  320.   switch (c)
  321.    {
  322.    case '+': origin_z += 50;
  323.          if (origin_z > 3000) 
  324.            origin_z = 3000;
  325.          break;
  326.    case '-': origin_z -= 50;
  327.          if (origin_z < 200) 
  328.            origin_z = 200;
  329.          break;
  330.    case '8': curx += 5;
  331.          break;
  332.    case '7': curx -= 5;      
  333.          break;
  334.    case '5': cury += 5;      
  335.          break;
  336.    case '4': cury -= 5;      
  337.          break;
  338.    case '2': curz += 5;      
  339.          break;
  340.    case '1': curz -= 5;      
  341.          break;
  342.   }
  343.  
  344.   if (curx > 359) 
  345.     curx -= 359;
  346.   if (cury > 359) 
  347.     cury -= 359;
  348.   if (curz > 359) 
  349.     curz -= 359;
  350.   if (curx < 0) 
  351.     curx += 359;
  352.   if (cury < 0) 
  353.     cury += 359;
  354.   if (curz < 0) 
  355.     curz += 359;
  356. }
  357.  
  358.  
  359.  
  360. void bounce_object (void)
  361. {
  362.   xpos += xdir * 4;
  363.   ypos += ydir * 4;
  364.   zpos += zdir * 4;
  365.  
  366.   if (xpos > 400)
  367.     xdir = -1;
  368.   if (ypos > 200)
  369.     ydir = -1;
  370.   if (zpos > -100)
  371.     zdir = -1;
  372.  
  373.   if (xpos < -400)
  374.     xdir = 1;
  375.   if (ypos < -200)
  376.     ydir = 1;
  377.   if (zpos < -900)
  378.     zdir = 1;
  379.  
  380.   move_x = xpos;
  381.   move_y = ypos;
  382.   move_z = zpos;
  383. }
  384.  
  385.  
  386.  
  387. void main(void)
  388. {
  389.   short oldmode;
  390.  
  391.   if ( !vgadetected () )
  392.   {
  393.     printf ("Error - VGA card required for any WGT program.\n");
  394.     exit (0);
  395.   }
  396.   printf ("WGT Example #54\n\n");
  397.   printf ("A simple 3D object is shown on the screen.\n");
  398.   printf ("You can use the following keys:.\n");
  399.   printf ("+  Move backwards\n");
  400.   printf ("-  Move forwards\n");
  401.   printf ("8  Increase X rotation\n");
  402.   printf ("7  Decrease X rotation\n");
  403.   printf ("5  Increase Y rotation\n");
  404.   printf ("4  Decrease Y rotation\n");
  405.   printf ("2  Increase Z rotation\n");
  406.   printf ("1  Decrease Z rotation\n");
  407.   printf ("q  Quits the program\n");
  408.   printf ("Turn NUMLOCK on to use the numeric keypad.\n");
  409.   printf ("\n\nPress any key to continue.\n");
  410.   getch();
  411.   
  412.   
  413.   oldmode = wgetmode ();
  414.   vga256 ();
  415.  
  416.   winit3d ();
  417.   winitpoly (WGT_SYS.yres);
  418.  
  419.   other = wnewblock (0, 0, 319, 199);
  420.   wloadpalette ("3ddemo.pal", pal);
  421.   wsetpalette (0, 255, pal);
  422.  
  423.   maxpoly = 0;
  424.   loadobject ("mytri.3d");
  425.   wsetscreen (other);
  426.  
  427.   /* Main loop */
  428.   do {
  429.     thisrect.x1 = 319;
  430.     thisrect.y1 = 199;
  431.     thisrect.x2 = 0;
  432.     thisrect.y2 = 0;
  433.  
  434.     clear_last ();
  435.  
  436.     wsetrotation (curx, cury, curz);
  437.  
  438.     bounce_object ();
  439.     wrotatepoints (&mypoints, &finp, 8);
  440.  
  441.     calculate_depth ();
  442.     sort_polys ();
  443.     draw_polys ();
  444.     get_response ();
  445.     wretrace ();
  446.     update_screen ();
  447.   } while (c != 'Q');
  448.   wdeinitpoly ();
  449.   wsetmode (oldmode);
  450. }
  451.